package com.sean.iphoneAppWorkspace;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;

/**
 * 滑动View控件
 * @author 郑澍璋
 *
 */
public class ScrollViewGroup extends ViewGroup implements OnGestureListener {

	public static final String tag = "CScrollView";
	
	public static final int TOUCH_STATUS_NORMAL = 0;
	public static final int TOUCH_STATUS_FLING = 1;
	public static final int TOUCH_STATUS_SCROLLING = 2;
	public static final int TOUCH_STATUS_MOVING = 3;
	
	/** 滚动一屏所花的时间*/
	private static final int SCROLL_ANIMATION_TIME = 1000;
	/** 首屏和尾屏的超屏数值*/
	private static final int SCREEN_OFFSET = 100;
	
	public int mStatus = TOUCH_STATUS_NORMAL;
	
	protected GestureDetector mGestureDetector;
	protected Scroller mScroller;
	
	private int mCurrentPosX = 0;
	private int mLastPosX;
	private int mCurrentScreen = 0;
	private int mDownPosX = 0;
	
	private IndicatorControl mIndicatorControl;
	
	public ScrollViewGroup(Context context, AttributeSet attrs) {
		super(context, attrs);
		mGestureDetector = new GestureDetector(this);
		mScroller = new Scroller(context);
	}

	public ScrollViewGroup(Context context) {
		super(context);
		mGestureDetector = new GestureDetector(this);
		mScroller = new Scroller(context);
	}
	
	/**
	 * 设置指示控制器
	 * @param indicatorControl 指示控制器
	 */
	public void setIndicatorControl(IndicatorControl indicatorControl) {
		this.mIndicatorControl = indicatorControl;
		if(mIndicatorControl != null) {
			indicatorControl.setCount(this.getChildCount());
		}
	}

	/**
	 * 计算每个子控件的位置
	 */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		final int childCount = getChildCount();
		int left = 0;
		View child = null;
		for(int i = 0; i < childCount; i++) {
			child = getChildAt(i);
			if(child.getVisibility() == View.GONE) 
				continue;
			final int width = child.getMeasuredWidth();
			child.layout(left, 0, left + width, child.getMeasuredHeight());
			left += width;
		}
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		final int childCount = getChildCount();
		View child = null;
		for(int i = 0; i < childCount; i++) {
			child = getChildAt(i);
			child.measure(widthMeasureSpec, heightMeasureSpec);
//			Log.d(tag, "width = " + MeasureSpec.getSize(widthMeasureSpec) + "; height = " + MeasureSpec.getSize(heightMeasureSpec));
		}
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent event) {
		
		switch(event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.d(tag, "onInterceptTouchEvent => ACTION_DOWN");
			return false;
		//触屏移动时，则传递事件到OnTouch事件
		case MotionEvent.ACTION_MOVE:
			Log.d(tag, "onInterceptTouchEvent => ACTION_MOVE");
			event.setAction(MotionEvent.ACTION_DOWN);
			return true;
		}
		Log.d(tag, "onInterceptTouchEvent => " + event.getAction());
		return true;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		final int x = (int)event.getX();
		
		mGestureDetector.onTouchEvent(event);
		
		switch(event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.d(tag, "onTouchEvent => ACTION_DOWN");
			
			if(!mScroller.isFinished()) {
				mScroller.abortAnimation();
			}
			mStatus = TOUCH_STATUS_MOVING;
			mLastPosX = mCurrentPosX;
			mDownPosX = x;
		case MotionEvent.ACTION_MOVE:
			Log.d(tag, "onTouchEvent => ACTION_MOVE");
			
			//计算当前滚动到的坐标
			mCurrentPosX = mLastPosX + mDownPosX - x;
			//屏幕第一屏和最后一屏越界不能超过10
			mCurrentPosX = Math.max(
					Math.min(mCurrentPosX, (getChildCount() - 1)
							* getMeasuredWidth() + SCREEN_OFFSET), -SCREEN_OFFSET);
//			Log.d(tag, "mCurrentX = " + mCurrentPosX + "; mDownPosX = " + mDownPosX + "; x = " + x);
			scrollTo(mCurrentPosX, 0);
			break;
		case MotionEvent.ACTION_UP:
			Log.d(tag, "onTouchEvent => ACTION_UP");
			
			//计算当前滚动到的屏幕,如果已触发FLING事件，则不用计算当前屏幕，因为已在onFling事件中计算出来了
			if(mStatus != TOUCH_STATUS_FLING)
				mCurrentScreen = calculateScreen(mCurrentPosX);
//			Log.d(tag, "mCurrentScreen = " + mCurrentScreen);
			scrollTo(mCurrentScreen);
			break;
		}
		return true;
	}
	

	/**
	 * 将控件滚动到指定Subview
	 * @param screenIndex
	 */
	public void scrollTo(int screenIndex) {
		int targetX = screenIndex * getMeasuredWidth();
//		Log.d(tag, "getMeasuredWidth = " + getMeasuredWidth());
		
		//计算执行滚动事件所花的时间
		int time = Math.abs(mCurrentPosX - screenIndex * getMeasuredWidth()) 
				* SCROLL_ANIMATION_TIME / getMeasuredWidth();
		mStatus = TOUCH_STATUS_SCROLLING;
//		Log.d(tag, "mCurrentPosX = " + mCurrentPosX + "; targetX -mCurrentPosX = " + (targetX -mCurrentPosX));
		mScroller.startScroll(mCurrentPosX, 0, targetX - mCurrentPosX , 0, time);
		computeScroll();
	}
	
	@Override
	public void computeScroll() {
		if(mStatus == TOUCH_STATUS_SCROLLING && mScroller.computeScrollOffset()) {
			scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
			mCurrentPosX = mScroller.getCurrX();
			postInvalidate();
		} else if(mStatus == TOUCH_STATUS_SCROLLING) {
			mStatus = TOUCH_STATUS_NORMAL;
			mCurrentPosX = mScroller.getCurrX();
			
			if(mIndicatorControl != null) {
				mIndicatorControl.setSelected(calculateScreen(mCurrentPosX));
			}
		}
	}
	
	/**
	 * 通过当前所在坐标计算出屏幕属于哪一屏
	 * @param curPos 当前坐标
	 */
	private int calculateScreen(int curPos) {
		int curScreen = curPos / getMeasuredWidth();
		if((curPos - curScreen * getMeasuredWidth()) > getMeasuredWidth() / 2) {
			curScreen ++;
		}
		return Math.min(Math.max(0, curScreen), getChildCount() - 1);
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
//		Log.i(tag, "Fling >> velocityX : " + velocityX + "; velocityY : " + velocityY);
//		Log.i(tag, "Fling >> event1 : " + e1.getX() + ", " + e1.getY() + ";  event2 : " + e2.getX() + ", " + e2.getY());
		mStatus = TOUCH_STATUS_FLING;
		if(velocityX > 0) {
			mCurrentScreen = Math.max(mCurrentScreen - 1, 0);
		} else {
			mCurrentScreen = Math.min(mCurrentScreen + 1, getChildCount() - 1);
		}
		return false;
	}
	
	

	public void requestInvalidate(int width) {
		mCurrentPosX = width * mCurrentScreen;
		scrollTo(mCurrentPosX, 0);
	}

	@Override
	public boolean onDown(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onShowPress(MotionEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onLongPress(MotionEvent e) {
		// TODO Auto-generated method stub
		
	}
	
	/**
	 * 指示器控制接口
	 * @author 郑澍璋
	 */
	public static interface IndicatorControl {
		
		/**
		 * 设置指示索引的数量
		 */
		public void setCount(int count);
		
		/**
		 * 获取当前所指示的索引值
		 */
		public int getCount();
		
		/**
		 * 设置当前选中哪一项
		 */
		public void setSelected(int index);
	}
}
